home *** CD-ROM | disk | FTP | other *** search
- // System 7.1 font folder patch
- // version 1.1
- // joe holt 20 july 1993
-
- #include <GestaltEqu.h>
- #include <Folders.h>
-
- static OSErr patch_system( void );
- OSErr DuplicateFile( FSSpecPtr source, FSSpecPtr destination );
-
- #define k_Failed_ALRT 128
- #define k_progress_DLOG 129
- #define k_Succeeded_ALRT 130
-
- Boolean Success( Boolean condition, int string_index );
-
- enum {
- k_failed_not_system_71 = 1,
- k_failed_unknown_system,
- k_failed_already_tuned,
- k_failed_cant_update,
- k_failed_cant_update_disk_full,
- k_failed_cant_update_disk_error,
- k_failed_cant_update_and_system_is_in_trash,
- k_failed_cant_update_and_system_has_funny_name
- };
-
-
- static unsigned char *strings;
- static int num_strings;
-
-
- #define assert(condition) \
- ( (condition) ? 1 : (assertFailed( __FILE__, __LINE__, #condition ), 0) )
- static void assertFailed( char *file, long line, char *condition );
- void assertFailed( char *file, long line, char *condition )
- {
- unsigned char text[256];
- unsigned char num[20];
- char *s;
- unsigned char *d;
- int i;
-
- d = &text[1];
-
- i = 0;
- if ( line > 1000 ) {
- num[++i] = '0' + line / 1000;
- line %= 1000;
- }
- if ( line > 100 ) {
- num[++i] = '0' + line / 100;
- line %= 100;
- }
- if ( line > 10 ) {
- num[++i] = '0' + line / 10;
- line %= 10;
- }
- num[++i] = '0' + line;
- num[0] = i;
-
- for ( s = file; *s; ) *d++ = *s++;
- for ( s = ", line "; *s; ) *d++ = *s++;
- for ( i = num[0], s = (char *) &num[1]; i; --i ) *d++ = *s++;
- for ( s = ": ("; *s; ) *d++ = *s++;
- for ( s = condition; *s; ) *d++ = *s++;
- for ( s = ") failed"; *s; ) *d++ = *s++;
- text[0] = d - &text[1];
-
- DebugStr( text );
- ExitToShell();
- }
-
-
- void main( void );
- void main( void )
- {
- Handle h;
- OSErr result;
- long response;
- EventRecord the_event;
- int i;
- DialogPtr dialog;
-
- MaxApplZone();
- InitGraf( &thePort );
- InitFonts();
- InitWindows();
- InitDialogs( nil );
- TEInit();
- InitMenus();
- InitCursor();
- for ( i = 5; i; --i ) OSEventAvail( 0, &the_event );
-
- h = GetResource( 'STR#', 128 );
- assert( h );
- MoveHHi( h );
- HLock( h );
- num_strings = **(short **)h;
- strings = (unsigned char *) StripAddress( *h + 2 );
-
-
- // quick check to make sure this is System 7.1
-
- result = Gestalt( gestaltSystemVersion, &response );
- if ( !Success( !result && response == 0x0710, k_failed_not_system_71 ) ) return;
-
-
- // let's try patching it; put up the "please wait" dialog
-
- SetCursor( *GetCursor( watchCursor ) );
- dialog = GetNewDialog( k_progress_DLOG, nil, (WindowPtr) -1 );
- assert( dialog );
- DrawDialog( dialog );
-
-
- // try the patch
-
- result = patch_system();
-
-
- // put the dialog away; if everything worked, put up an alert saying so
-
- DisposeDialog( dialog );
- if ( result == noErr ) NoteAlert( k_Succeeded_ALRT, nil );
- }
-
-
- static OSErr patch_system( void )
- {
- Boolean destination_created, destination_open;
- Handle h;
- Ptr p;
- short attr;
- FCBPBRec infoPB;
- CMovePBRec movePB;
- HParamBlockRec renamePB;
- Str63 name;
- FSSpec source, destination;
- OSErr result;
- short ref;
-
- destination_created = false;
- destination_open = false;
- h = nil;
- result = noErr;
-
-
- // get the location of the system file
-
- infoPB.ioNamePtr = name;
- infoPB.ioFCBIndx = 0;
- infoPB.ioRefNum = 2;
- result = PBGetFCBInfo( &infoPB, false );
- if ( !Success( result == noErr, k_failed_cant_update_disk_error ) ) goto exit;
-
-
- // make up FSSpecs for the original and duplicate system files;
- // put the duplicate in the root folder with a random name
-
- FSMakeFSSpec( infoPB.ioFCBVRefNum, infoPB.ioFCBParID, infoPB.ioNamePtr, &source );
- NumToString( TickCount(), name );
- FSMakeFSSpec( infoPB.ioFCBVRefNum, 2, name, &destination );
-
-
- // duplicate the system file
-
- result = DuplicateFile( &source, &destination );
- if ( !Success( result != dskFulErr, k_failed_cant_update_disk_full ) ) goto exit;
- if ( !Success( result == noErr, k_failed_cant_update_disk_error ) ) goto exit;
- destination_created = true;
-
-
- // open up the resource fork of the duplicate
-
- ref = FSpOpenResFile( &destination, fsRdWrPerm );
- result = (ref != -1 ? noErr : 1);
- if ( !Success( result == noErr, k_failed_cant_update ) ) goto exit;
- destination_open = true;
-
-
- // the the resource to patch; it's coming into our heap
-
- h = Get1Resource( 'lpch', 31 );
- result = ResError();
- if ( !Success( result == noErr, k_failed_unknown_system ) ) goto exit;
-
-
- // some sanity checks to make sure this is the right system;
- // plus a check to see if this system has already been tuned
-
- result = (GetHandleSize( h ) == 254504 ? noErr : 1);
- if ( !Success( result == noErr, k_failed_unknown_system ) ) goto exit;
-
- HLock( h );
- p = *h + 211513;
- result = (*p != 0x2E ? noErr : 1);
- if ( !Success( result == noErr, k_failed_already_tuned ) ) goto exit;
- result = (*p == 0x6E ? noErr : 1);
- if ( !Success( result == noErr, k_failed_unknown_system ) ) goto exit;
-
-
- // the patch! all this code for a 1 byte change...
-
- *p = 0x2E;
-
-
- // now change the resource info to uncompressed and mark it changed
- attr = GetResAttrs( h );
- result = ResError();
- if ( !Success( result == noErr, k_failed_cant_update ) ) goto exit;
- SetResAttrs( h, attr & ~(mapCompact << 8) );
- result = ResError();
- if ( !Success( result == noErr, k_failed_cant_update ) ) goto exit;
- ChangedResource( h );
- result = ResError();
- if ( !Success( result == noErr, k_failed_cant_update ) ) goto exit;
-
-
- // write it back out
-
- UpdateResFile( ref );
- result = ResError();
- if ( !Success( result == noErr, k_failed_cant_update ) ) goto exit;
-
-
- // get rid of the resource (to be nice) and close the duplicate file
-
- ReleaseResource( h );
- h = nil;
- CloseResFile( ref );
- result = ResError();
- if ( !Success( result == noErr, k_failed_cant_update ) ) goto exit;
- destination_open = false;
-
-
- // now move the original system file into the trash
-
- result = FindFolder( source.vRefNum, kTrashFolderType, kCreateFolder,
- &movePB.ioVRefNum, &movePB.ioNewDirID );
- if ( !Success( result == noErr, k_failed_cant_update ) ) goto exit;
-
- movePB.ioNamePtr = source.name;
- movePB.ioVRefNum = source.vRefNum;
- movePB.ioDirID = source.parID;
- movePB.ioNewName = nil;
-
- result = PBCatMove( &movePB, false );
- if ( !Success( result == noErr, k_failed_cant_update ) ) goto exit;
-
-
- // move the patched system file into the system folder (using the original file's location)
-
- movePB.ioNamePtr = destination.name;
- movePB.ioVRefNum = destination.vRefNum;
- movePB.ioDirID = destination.parID;
-
- movePB.ioNewDirID = source.parID;
-
- result = PBCatMove( &movePB, false );
- if ( !Success( result == noErr, k_failed_cant_update_and_system_is_in_trash ) ) goto exit;
-
-
- // finally, change the patched system file's name to what the original system file was named
-
- renamePB.fileParam.ioNamePtr = destination.name;
- renamePB.fileParam.ioVRefNum = source.vRefNum;
- renamePB.fileParam.ioDirID = source.parID;
- renamePB.ioParam.ioMisc = (Ptr) source.name;
- result = PBHRename( &renamePB, false );
- if ( !Success( result == noErr, k_failed_cant_update_and_system_has_funny_name ) ) goto exit;
-
- exit:
- if ( h ) {
- ReleaseResource( h );
- h = nil;
- }
- if ( destination_open ) {
- CloseResFile( ref );
- destination_open = false;
- }
-
- if ( result && destination_created ) {
- HParamBlockRec deletePB;
-
- deletePB.fileParam.ioNamePtr = (StringPtr) &destination.name;
- deletePB.fileParam.ioVRefNum = destination.vRefNum;
- deletePB.fileParam.ioDirID = destination.parID;
- PBHDelete( &deletePB, false ); // ignore result, since it may've moved
- }
-
- return result;
- }
-
-
- Boolean Success( Boolean condition, int string_index )
- {
- unsigned char *s;
-
- if ( condition ) return true;
-
- assert( string_index > 0 && string_index <= num_strings );
-
- s = strings;
- while ( --string_index ) s += *s + 1;
-
- ParamText( s, nil, nil, nil );
- InitCursor();
- StopAlert( k_Failed_ALRT, nil );
-
- return false;
- }
-
-
- // a quick and dirty file duplicate routine.
-
- // actually, it's pretty good, if I should say so myself. the only area that could
- // be improved is the allocation of the temporary duplication buffer.
-
- #define kDuplicateFileBufferSize (200000)
-
- static OSErr duplicate_fork( FSSpecPtr source, FSSpecPtr destination, short fork );
- static OSErr copy_finfo( FSSpecPtr source, FSSpecPtr destination );
-
-
- OSErr DuplicateFile( FSSpecPtr source, FSSpecPtr destination )
- {
- OSErr result;
-
- result = noErr;
-
- result = duplicate_fork( source, destination, 0 );
- if ( result ) goto exit;
-
- result = duplicate_fork( source, destination, 1 );
- if ( result ) goto exit;
-
- result = copy_finfo( source, destination );
- if ( result ) goto exit;
-
- exit:
- return result;
- }
-
-
- static OSErr duplicate_fork( FSSpecPtr source, FSSpecPtr destination, short fork )
- {
- Boolean source_open, destination_created, destination_open;
- HParamBlockRec sourcePB, destinationPB, flushPB;
- OSErr result;
- Handle buffer_handle;
- Ptr buffer;
-
- source_open = false;
- destination_created = (fork == 1);
- destination_open = false;
- buffer_handle = nil;
- result = noErr;
-
- sourcePB.fileParam.ioNamePtr = (StringPtr) &source->name;
- sourcePB.fileParam.ioVRefNum = source->vRefNum;
- sourcePB.fileParam.ioDirID = source->parID;
-
- sourcePB.ioParam.ioPermssn = fsRdPerm;
- sourcePB.ioParam.ioMisc = nil;
-
- if ( fork == 0 ) result = PBHOpenDF( &sourcePB, false );
- else result = PBHOpenRF( &sourcePB, false );
- if ( result ) goto exit;
- source_open = true;
-
-
- buffer_handle = TempNewHandle( kDuplicateFileBufferSize, &result );
- if ( result ) goto exit;
- HLock( buffer_handle );
- buffer = *buffer_handle;
-
- destinationPB.fileParam.ioNamePtr = (StringPtr) &destination->name;
- destinationPB.fileParam.ioVRefNum = destination->vRefNum;
- destinationPB.fileParam.ioDirID = destination->parID;
- destinationPB.fileParam.ioFlVersNum = 0;
-
- if ( fork == 0 ) {
- result = PBHCreate( &destinationPB, false );
- if ( result ) goto exit;
- destination_created = true;
- }
-
- destinationPB.ioParam.ioPermssn = fsRdWrPerm;
- destinationPB.ioParam.ioMisc = nil;
-
- if ( fork == 0 ) result = PBHOpenDF( &destinationPB, false );
- else result = PBHOpenRF( &destinationPB, false );
- if ( result ) goto exit;
- destination_open = true;
-
-
- sourcePB.ioParam.ioBuffer = buffer;
- sourcePB.ioParam.ioPosOffset = 0;
- sourcePB.ioParam.ioPosMode = fsFromStart;
-
- destinationPB.ioParam.ioBuffer = buffer;
- destinationPB.ioParam.ioPosOffset = 0;
- destinationPB.ioParam.ioPosMode = fsFromStart;
-
- for ( ;; ) {
- sourcePB.ioParam.ioReqCount = kDuplicateFileBufferSize;
- result = PBRead( (ParmBlkPtr) &sourcePB, false );
- if ( result == eofErr ) result = noErr;
- if ( result ) goto exit;
-
- if ( sourcePB.ioParam.ioActCount == 0 ) break;
-
- destinationPB.ioParam.ioReqCount = sourcePB.ioParam.ioActCount;
- result = PBWrite( (ParmBlkPtr) &destinationPB, false );
- if ( result ) goto exit;
- }
-
-
- exit:
- if ( buffer_handle ) {
- DisposeHandle( buffer_handle );
- buffer_handle = nil;
- }
-
- if ( source_open ) {
- PBClose( (ParmBlkPtr) &sourcePB, false );
- source_open = false;
- }
-
- if ( destination_open ) {
- PBClose( (ParmBlkPtr) &destinationPB, false );
- destination_open = false;
- }
-
- if ( destination_created && result ) {
- destinationPB.fileParam.ioDirID = destination->parID;
- PBHDelete( &destinationPB, false );
- destination_created = false;
- }
-
- flushPB.volumeParam.ioNamePtr = nil;
- flushPB.volumeParam.ioVRefNum = destination->vRefNum;
- PBFlushVol( (ParmBlkPtr) &flushPB, false );
-
-
- return result;
- }
-
-
- static OSErr copy_finfo( FSSpecPtr source, FSSpecPtr destination )
- {
- CInfoPBRec sourcePB, destinationPB;
- OSErr result;
-
- result = noErr;
-
-
- sourcePB.hFileInfo.ioNamePtr = (StringPtr) &source->name;
- sourcePB.hFileInfo.ioVRefNum = source->vRefNum;
- sourcePB.hFileInfo.ioDirID = source->parID;
-
- sourcePB.hFileInfo.ioFDirIndex = 0;
-
- result = PBGetCatInfo( &sourcePB, false );
- if ( result ) goto exit;
-
-
- destinationPB = sourcePB;
-
- destinationPB.hFileInfo.ioNamePtr = (StringPtr) &destination->name;
- destinationPB.hFileInfo.ioVRefNum = destination->vRefNum;
- destinationPB.hFileInfo.ioDirID = destination->parID;
-
- destinationPB.hFileInfo.ioFDirIndex = 0;
-
- result = PBSetCatInfo( &destinationPB, false );
- if ( result ) goto exit;
-
- exit:
- if ( result ) {
- HParamBlockRec deletePB;
-
- deletePB.fileParam.ioNamePtr = (StringPtr) &destination->name;
- deletePB.fileParam.ioVRefNum = destination->vRefNum;
- deletePB.fileParam.ioDirID = destination->parID;
- PBHDelete( &deletePB, false );
- }
-
- return result;
- }
-